//
//  TCPClientManager.swift
//  NetAction
//
//  Created by zcj on 2025/1/14.
//

import Foundation
import NetAction

enum SplitError:Error{
    case dataLeft
}

//管理tcpclient以及其发送功能
class TCPClientManager{
    public static var shared:TCPClientManager = TCPClientManager()
    
    //dic 存放所有的tcpclient，虽然listener 使用的是id（通过connection获得），
    //但这里不能先获得connection，所以推荐使用ip字符串，来获得id
    var clientDic:Dictionary<ConId,TCPClient> = Dictionary()
    
    func getTCPClient(ip:String,port:UInt16) -> TCPClient{
        let id = Cal.hashOfString(str: ip)
        if let client = clientDic[id]{
            return client
        }else{
            let client = TCPClient(host: ip, port: port)
            client.conId = id
            clientDic[id] = client
            client.start()
            return client
        }
    }
    
    func sendStringMsg(ip:String,str:String) -> Int64{
        let client = getTCPClient(ip: ip, port:NetMessage.shared().tcpPort)
        let strMsg = StringMessage()
        strMsg.hostName = NetMessage.shared().hostName
        strMsg.message = str
        client.addTask( data: strMsg)
        return client.conId
    }
    
    func sendFileMsg(ip:String,filePath:String) -> Int64{
        let client = getTCPClient(ip: ip, port:NetMessage.shared().tcpPort)
        
        let fileUrl = URL(fileURLWithPath:filePath)
        let url = URL(string: filePath)
        let fileName = url?.lastPathComponent
        let fileId = getFileId(remoteIp: ip, localIp: NetMessage.shared().getIPAddress(), fileName: fileName ?? "")
        
        let totalSize = FileController.fileSize(fileUrl: url!)
        let ftm = FileTransMessage(fileName: fileName,totalSize: totalSize,downloadSize: 0,absolutePath:filePath)
        ftm.fileId = fileId
        ftm.conID = client.conId
        ftm.ip = ip
        client.fileDic[ftm.fileId] = ftm;//client增加发送的文件请求信息
        
        //生成filemessage,添加task
        let fm = FileMessage()
        fm.fileName = fileName!
        fm.fileId = fileId
        fm.totalSize = FileController.fileSize(fileUrl: fileUrl)!
        
        client.addTask(data: fm)
        return client.conId
    }
    
    func sendReconnectMsg(ip:String,side:INT32,type:INT32) -> Int64{
        let client = getTCPClient(ip: ip, port:NetMessage.shared().tcpPort)
        let reconnect = ReConnect(side: side,type:type)
        client.addTask(data: reconnect)
        return client.conId
    }
    
    func sendBaseData(ip:String,task:BaseData) -> Int64{
        let client = getTCPClient(ip: ip, port:NetMessage.shared().tcpPort)
        client.addTask(data: task)
        return client.conId
    }
    
    
    
    //将数据data切割成段的数据，各自进行处理，这里是公用的，只是处理PackageHead类型的包用的
    public static func splitDatawithConnection(data:Data,callback:@escaping (_ ph:PackageHead?,_ data:Data,_ status:Bool)->()){
        var index:Int = 0;
        var status:Bool = false
        while(true){
            let lenofph = PackageHead.headCount
            if(index+Int(lenofph) > data.count ){
                //                print("PackageHead.length is grater than data.count")
                //还有一些没有读完
                status = true
                break;
            }
            let phData = data.subdata(in: index..<index+Int(lenofph))
            let ph:PackageHead = PackageHead.decode(data: phData)!
            if(index+Int(ph.dataCount) > data.count ){
                //                print("PackageHead.dataCount is grater than data.count")
                //还有一些没有读完
                status = true
                break;
            }
            let msgData = data.subdata(in: index+Int(lenofph)..<index+Int(ph.dataCount))
            
            //处理
            callback(ph,msgData,false)
            
            index = index+Int(ph.dataCount)
            if(index > data.count){
                //刚好读完
                break
            }
        }
        if status {
            callback(nil,data.subdata(in: index..<data.count),true)
            //            if let connectionMessage = TCPListener.connectionDic[connectionWrapper]{
            //                connectionMessage.lastData = data.subdata(in: index..<data.count)
            //            }
        }
        print("this data were read")
        
    }
}
